/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       window_background.cpp

	$Header: /game/window_background.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "window_background.h"

#include "adaptor_handler.h"
#include "bitmap_layer_window.h"
#include "bound_handler.h"
#include "button.h"
#include "dialog_box_bitmaps.h"
#include "dialog_box_cache.h"
#include "mouse_event.h"
#include "pixel_24.h"
#include "platform.h"

t_window_background::t_window_background( t_cached_ptr<t_dialog_box_bitmaps> const& bitmaps,
										  t_window* parent ) 
				   : t_window( k_completely_transparent, parent )
{
	// get bitmaps
	m_bitmaps = bitmaps;
	construct();
}

t_window_background::t_window_background( t_cached_ptr<t_dialog_box_bitmaps> const& bitmaps,
										  t_screen_rect const& rect, t_window* parent )
            : t_window( k_completely_transparent, parent )
{
	// get bitmaps
	m_bitmaps = bitmaps;
	construct();
	init( rect );
}

// -============================================================
// initialize dialog box
// -============================================================
void t_window_background::construct()
{
	t_bitmap_layer const* top_left = m_bitmaps->get_top_left();
	t_bitmap_layer const* top_right = m_bitmaps->get_top_right();
	t_bitmap_layer const* left				= m_bitmaps->get_left();
	t_bitmap_layer const* bottom			= m_bitmaps->get_bottom();
	t_bitmap_layer const* bottom_left = m_bitmaps->get_bottom_left();
	t_bitmap_layer const* bottom_right = m_bitmaps->get_bottom_right();
	t_bitmap_layer const* right				= m_bitmaps->get_right();
	t_bitmap_layer const* top				= m_bitmaps->get_top();
	t_screen_rect         top_left_rect = top_left->get_rect();
	t_screen_rect         top_right_rect = top_right->get_rect();
	t_screen_rect		  bottom_left_rect = bottom_left->get_rect();
	t_screen_rect		  bottom_right_rect = bottom_right->get_rect();
	t_screen_rect		  bottom_rect		= bottom->get_rect();
	t_screen_rect		  left_rect			= left->get_rect();
	t_screen_rect		  right_rect		= right->get_rect();
	t_screen_rect		  top_rect			= top->get_rect();

	m_border_extents = get_extent( bottom_right_rect, bottom_rect );
	m_border_extents = get_extent( m_border_extents, bottom_left_rect );
	m_border_extents = get_extent( m_border_extents, right_rect );
	m_border_extents = get_extent( m_border_extents, left_rect );
	m_border_extents = get_extent( m_border_extents, top_right_rect );
	m_border_extents = get_extent( m_border_extents, top_rect );
	m_border_extents = get_extent( m_border_extents, top_left_rect );

	// compute border
	t_bitmap_layer const* layer = m_bitmaps->find( "client_area" );
	t_screen_rect         client_area = layer->get_rect();

	m_margin.top    = client_area.top - m_border_extents.top;
	m_margin.left   = client_area.left - m_border_extents.left;
	m_margin.right  = m_border_extents.right - client_area.right;
	m_margin.bottom = m_border_extents.bottom - client_area.bottom;
}

// -============================================================
// initialize dialog box
// -============================================================
void t_window_background::init( t_screen_rect const& rect )
{
	t_window*             child;
	t_bitmap_layer const* layer;
	t_screen_point        point;
	int                   stop;
	t_screen_point        offset;
	t_screen_rect         client_rect = rect - rect.top_left();
	t_bitmap_layer const* top_left = m_bitmaps->get_top_left();
	t_bitmap_layer const* top_right = m_bitmaps->get_top_right();
	t_bitmap_layer const* bottom			= m_bitmaps->get_bottom();
	t_bitmap_layer const* bottom_left = m_bitmaps->get_bottom_left();
	t_bitmap_layer const* bottom_right = m_bitmaps->get_bottom_right();
	t_bitmap_layer const* right				= m_bitmaps->get_right();
	t_screen_point		  origin;
	t_screen_rect         top_left_rect = top_left->get_rect();
	t_screen_rect         top_right_rect = top_right->get_rect();
	t_screen_rect		  bottom_left_rect = bottom_left->get_rect();
	t_screen_rect		  bottom_right_rect = bottom_right->get_rect();
	t_screen_rect		  bottom_rect		= bottom->get_rect();
	t_screen_rect		  right_rect		= right->get_rect();
	int                   bottom_offset;
	int                   right_offset;

	origin = m_border_extents.top_left();

	bottom_offset = client_rect.bottom - m_border_extents.height();
	right_offset  = client_rect.right - m_border_extents.width();

	// create top left corner
	child = new t_bitmap_layer_window( top_left, -origin, this );
	child->move_to_back();

	// create top right corner
	child = new t_bitmap_layer_window( top_right, t_screen_point( right_offset, 0) - origin,
		                               this );
	child->move_to_back();

	// create bottom left corner
	child = new t_bitmap_layer_window( bottom_left, 
		                               t_screen_point( 0, bottom_offset) - origin, this );
	child->move_to_back();

	// create bottom right corner
	child = new t_bitmap_layer_window( bottom_right, 
									   t_screen_point( right_offset, bottom_offset )
									   - origin, this );
	child->move_to_back();

	// create left edge
	t_screen_rect child_rect;

	layer   = m_bitmaps->get_left();
	point.x = 0;
	point.y = top_left_rect.bottom;
	stop    = bottom_left_rect.top + bottom_offset;
	offset  = t_screen_point( 0, layer->get_rect().top );
	offset  += origin;
	child   = 0;
	while (point.y < stop)
	{
		child = new t_bitmap_layer_window( layer, point - offset, this );
		child->move_to_back();
		point.y += layer->get_height();
	}
	// for last child, set rectangle to clip it.
	if (child != 0)
	{
		child_rect = to_client( child->get_screen_rect() );
		child_rect.bottom = bottom_left_rect.top + bottom_offset - origin.y;
		child->move( child_rect );
	}

	// create right edge
	layer   = m_bitmaps->get_right();
	point.x = right_offset;
	point.y = top_right_rect.bottom;
	stop    = bottom_right_rect.top + bottom_offset;
	offset  = t_screen_point( 0, layer->get_rect().top );
	offset += origin;
	child   = 0;
	while (point.y < stop)
	{
		child = new t_bitmap_layer_window( layer, point - offset, this );
		child->move_to_back();
		point.y += layer->get_height();
	}
	if (child != 0)
	{
		child_rect = to_client( child->get_screen_rect() );
		child_rect.bottom = bottom_right_rect.top + bottom_offset - origin.y;
		child->move( child_rect );
	}


	// create top edge
	layer   = m_bitmaps->get_top();
	point.x = top_left_rect.right;
	point.y = 0;
	stop    = top_right_rect.left + right_offset;
	offset  = t_screen_point( layer->get_rect().left, 0 );
	offset += origin;
	child   = 0;
	while (point.x < stop)
	{
		child = new t_bitmap_layer_window( layer, point - offset, this );
		child->move_to_back();
		point.x += layer->get_width();
	}
	if (child != 0)
	{
		child_rect = to_client( child->get_screen_rect() );
		child_rect.right = top_right_rect.left + right_offset - origin.x;
		child->move( child_rect );
	}

	// create bottom edge
	layer   = m_bitmaps->get_bottom();
	point.x = bottom_left_rect.right;
	point.y = bottom_offset;
	stop    = bottom_right_rect.left + right_offset;
	offset  = t_screen_point( layer->get_rect().left, 0 );
	offset += origin;
	child   = 0;
	while (point.x < stop)
	{
		child = new t_bitmap_layer_window( layer, point - offset, this );
		child->move_to_back();
		point.x += layer->get_width();
	}
	if (child != 0)
	{
		child_rect = to_client( child->get_screen_rect() );
		child_rect.right = bottom_right_rect.left + right_offset - origin.x;
		child->move( child_rect );
	}

	// create background pieces
	t_screen_rect background_rect = m_bitmaps->find( "background_rect" )->get_rect()
		                            - origin;
	t_screen_rect parchment_rect;

	background_rect.right = background_rect.right + right_offset;
	background_rect.bottom = background_rect.bottom + bottom_offset;

	layer  = m_bitmaps->get_background();
	offset = layer->get_rect().top_left();
	for (point.y = background_rect.top; point.y < background_rect.bottom;
	     point.y += layer->get_height() )
	{
		for (point.x = background_rect.left; point.x < background_rect.right;
		     point.x += layer->get_width())
		{
			child = new t_bitmap_layer_window( layer, point - offset, this );
			child->move_to_back();
			child_rect = to_client( child->get_screen_rect() );
			if (child_rect.right > background_rect.right)
				child_rect.right = background_rect.right;
			if (child_rect.bottom > background_rect.bottom)
				child_rect.bottom = background_rect.bottom;
			child->move( child_rect );
		}
	}

	t_window::init( rect );
}

// -============================================================
// set the click handler for a button so that it closes the window with a result
// -============================================================
void t_window_background::add_close_button( t_button* button, int result )
{
	button->set_click_handler( add_2nd_argument( bound_handler( *this, &t_window_background::close_click_result ), result ) );
}

// -============================================================
// respond to a button which closes the dialog
// -============================================================
void t_window_background::close_click( t_button* button )
{
	close();
}

// -============================================================
// respond to a button which closes the dialog and sets the return value
// -============================================================
void t_window_background::close_click_result( t_button* button, int result )
{
	m_return_value = result;
	close();
}

// -============================================================
// open such that the inner area corresponds to rect
// -============================================================
void t_window_background::open_around( t_screen_rect const& rect )
{
	t_screen_rect window_rect;
	t_screen_point top_left( get_left_border(), get_top_border() );

	window_rect.left = rect.left - top_left.x;
	window_rect.top = rect.top - top_left.y;
	// move children of window so border is new (0,0).
	t_window_list::iterator index = get_children_begin();
	t_window_list::iterator	end = get_children_end();
	t_window*				child;

	for (; index != end; ++index)
	{
		child = *index;
		child->move_screen_rect( child->get_screen_rect() + top_left );
	}

	window_rect.right = rect.right + get_right_border();
	window_rect.bottom = rect.bottom + get_bottom_border();
	init( window_rect );
}
